using System.Net.Http;
using System.Text;
using System.Text.Json;
using DocumentCreationSystem.Models;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;

namespace DocumentCreationSystem.Services;

/// <summary>
/// OpenAI服务实现
/// </summary>
public class OpenAIService : IAIService
{
    private readonly IConfiguration _configuration;
    private readonly ILogger _logger;
    private readonly HttpClient _httpClient;
    private readonly string _baseUrl;
    private readonly string? _apiKey;
    private readonly List<AIModel> _availableModels;
    private AIModel? _currentModel;

    public OpenAIService(IConfiguration configuration, ILogger logger)
    {
        _configuration = configuration;
        _logger = logger;
        _httpClient = new HttpClient();
        
        _baseUrl = configuration["BaseUrl"] ?? "https://api.openai.com/v1";
        _apiKey = configuration["ApiKey"];
        _availableModels = new List<AIModel>();
        
        ConfigureHttpClient();
        InitializeAvailableModels();
    }

    private void ConfigureHttpClient()
    {
        if (!string.IsNullOrWhiteSpace(_apiKey))
        {
            _httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {_apiKey}");
        }
        _httpClient.DefaultRequestHeaders.Add("User-Agent", "DocumentCreationSystem/1.0");
        _httpClient.Timeout = TimeSpan.FromSeconds(120); // 120秒，符合API请求最佳实践
    }

    private void InitializeAvailableModels()
    {
        // 添加OpenAI标准模型
        _availableModels.AddRange(new[]
        {
            new AIModel { Id = "gpt-3.5-turbo", Name = "GPT-3.5 Turbo", Provider = "OpenAI", IsAvailable = true },
            new AIModel { Id = "gpt-4", Name = "GPT-4", Provider = "OpenAI", IsAvailable = true },
            new AIModel { Id = "gpt-4-turbo", Name = "GPT-4 Turbo", Provider = "OpenAI", IsAvailable = true },
            new AIModel { Id = "gpt-4o", Name = "GPT-4o", Provider = "OpenAI", IsAvailable = true },
            new AIModel { Id = "gpt-4o-mini", Name = "GPT-4o Mini", Provider = "OpenAI", IsAvailable = true },
            // 用户要求的自定义模型
            new AIModel { Id = "Qwen3-30B-A3B", Name = "Qwen3-30B-A3B", Provider = "OpenAI", IsAvailable = true },
            new AIModel { Id = "Qwen3-32B", Name = "Qwen3-32B", Provider = "OpenAI", IsAvailable = true },
            new AIModel { Id = "QwQ-32B", Name = "QwQ-32B", Provider = "OpenAI", IsAvailable = true },
            new AIModel { Id = "QwQ-32B-AWQ", Name = "QwQ-32B-AWQ", Provider = "OpenAI", IsAvailable = true }
        });

        // 从配置中获取自定义模型
        var customModel = _configuration["Model"];
        if (!string.IsNullOrEmpty(customModel) && !_availableModels.Any(m => m.Id == customModel))
        {
            _availableModels.Add(new AIModel 
            { 
                Id = customModel, 
                Name = customModel, 
                Provider = "OpenAI", 
                IsAvailable = true 
            });
        }
    }

    public async Task<List<AIModel>> GetAvailableModelsAsync()
    {
        try
        {
            // 如果有API Key，尝试获取实际可用的模型列表
            if (!string.IsNullOrWhiteSpace(_apiKey))
            {
                await CheckModelAvailability();
            }
            
            return _availableModels.Where(m => m.IsAvailable).ToList();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取OpenAI模型列表失败");
            return _availableModels; // 返回默认列表
        }
    }

    private async Task CheckModelAvailability()
    {
        try
        {
            var url = $"{_baseUrl.TrimEnd('/')}/models";
            var response = await _httpClient.GetAsync(url);
            
            if (response.IsSuccessStatusCode)
            {
                var content = await response.Content.ReadAsStringAsync();
                var modelsResponse = JsonSerializer.Deserialize<JsonElement>(content);
                
                if (modelsResponse.TryGetProperty("data", out var modelsArray))
                {
                    var availableModelIds = new HashSet<string>();
                    foreach (var model in modelsArray.EnumerateArray())
                    {
                        if (model.TryGetProperty("id", out var idElement))
                        {
                            availableModelIds.Add(idElement.GetString() ?? "");
                        }
                    }
                    
                    // 更新模型可用性
                    foreach (var model in _availableModels)
                    {
                        model.IsAvailable = availableModelIds.Contains(model.Id);
                    }
                }
            }
        }
        catch (Exception ex)
        {
            _logger.LogWarning(ex, "检查OpenAI模型可用性失败，使用默认列表");
        }
    }

    public async Task<bool> SetCurrentModelAsync(string modelId)
    {
        var model = _availableModels.FirstOrDefault(m => m.Id == modelId);
        if (model == null)
        {
            _logger.LogWarning($"OpenAI模型不存在: {modelId}");
            return false;
        }

        // 测试模型是否可用
        if (!await CheckModelAvailabilityAsync(modelId))
        {
            _logger.LogWarning($"OpenAI模型不可用: {modelId}");
            return false;
        }

        _currentModel = model;
        _logger.LogInformation($"切换到OpenAI模型: {model.Name}");
        return true;
    }

    private async Task<bool> CheckModelAvailabilityAsync(string modelId)
    {
        try
        {
            var url = $"{_baseUrl.TrimEnd('/')}/chat/completions";
            
            var request = new
            {
                model = modelId,
                messages = new[]
                {
                    new { role = "user", content = "test" }
                },
                max_tokens = 1,
                temperature = 0.1
            };

            var json = JsonSerializer.Serialize(request);
            var content = new StringContent(json, Encoding.UTF8, "application/json");
            
            using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(120));
            var response = await _httpClient.PostAsync(url, content, cts.Token);
            
            return response.IsSuccessStatusCode;
        }
        catch (Exception ex)
        {
            _logger.LogWarning(ex, $"OpenAI模型连接测试失败: {modelId}");
            return false;
        }
    }

    public AIModel? GetCurrentModel()
    {
        return _currentModel;
    }

    public async Task<string> GenerateTextAsync(string prompt, int maxTokens = 2000, float temperature = 0.7f)
    {
        if (_currentModel == null)
        {
            throw new InvalidOperationException("未设置当前OpenAI模型");
        }

        const int maxRetries = 3;
        var retryDelay = TimeSpan.FromSeconds(2);

        for (int attempt = 1; attempt <= maxRetries; attempt++)
        {
            try
            {
                var url = $"{_baseUrl.TrimEnd('/')}/chat/completions";
                
                var request = new
                {
                    model = _currentModel.Id,
                    messages = new[]
                    {
                        new { role = "user", content = prompt }
                    },
                    max_tokens = maxTokens,
                    temperature = temperature,
                    stream = false
                };

                var json = JsonSerializer.Serialize(request);
                var content = new StringContent(json, Encoding.UTF8, "application/json");
                
                using var cts = new CancellationTokenSource(TimeSpan.FromMinutes(5));
                var response = await _httpClient.PostAsync(url, content, cts.Token);
                
                if (!response.IsSuccessStatusCode)
                {
                    var errorContent = await response.Content.ReadAsStringAsync();
                    throw new Exception($"OpenAI API调用失败 (状态码: {response.StatusCode}): {errorContent}");
                }

                var responseContent = await response.Content.ReadAsStringAsync();
                var responseJson = JsonSerializer.Deserialize<JsonElement>(responseContent);
                
                if (responseJson.TryGetProperty("choices", out var choices) && choices.GetArrayLength() > 0)
                {
                    var firstChoice = choices[0];
                    if (firstChoice.TryGetProperty("message", out var message) &&
                        message.TryGetProperty("content", out var messageContent))
                    {
                        return messageContent.GetString() ?? "";
                    }
                }
                
                throw new Exception("OpenAI API响应格式异常");
            }
            catch (TaskCanceledException)
            {
                if (attempt == maxRetries)
                    throw new Exception("OpenAI请求超时");
                
                _logger.LogWarning($"OpenAI请求超时，第 {attempt} 次重试");
                await Task.Delay(retryDelay);
                retryDelay = TimeSpan.FromSeconds(retryDelay.TotalSeconds * 2); // 指数退避
            }
            catch (Exception ex)
            {
                if (attempt == maxRetries)
                    throw;
                
                _logger.LogWarning(ex, $"OpenAI文本生成失败，第 {attempt} 次重试");
                await Task.Delay(retryDelay);
                retryDelay = TimeSpan.FromSeconds(retryDelay.TotalSeconds * 2);
            }
        }
        
        throw new Exception("OpenAI文本生成失败，已达到最大重试次数");
    }

    public async Task<string> PolishTextAsync(string text, string style = "通用")
    {
        var prompt = $@"请对以下文本进行润色，润色风格：{style}

原文：
{text}

润色要求：
1. 保持原意不变
2. 提升语言表达的流畅性和准确性
3. 增强文本的可读性
4. 根据指定风格调整语言特色

请直接返回润色后的文本：";

        return await GenerateTextAsync(prompt, text.Length + 500, 0.7f);
    }

    public async Task<string> ExpandTextAsync(string text, int targetLength, string? context = null)
    {
        var contextInfo = !string.IsNullOrEmpty(context) ? $"\n\n上下文信息：\n{context}" : "";

        var prompt = $@"请对以下文本进行扩写，目标长度约{targetLength}字符。

原文：
{text}{contextInfo}

扩写要求：
1. 保持原文的核心内容和风格
2. 增加细节描述、背景信息或相关内容
3. 确保扩写内容与原文自然衔接
4. 达到目标长度要求

请直接返回扩写后的文本：";

        return await GenerateTextAsync(prompt, targetLength + 500, 0.7f);
    }

    public async Task<string> GenerateChapterAsync(string outline, string? context = null, int targetWordCount = 6500)
    {
        var contextInfo = !string.IsNullOrEmpty(context) ? $"\n\n上下文信息：\n{context}" : "";

        var prompt = $@"请根据以下大纲创作章节内容，目标字数约{targetWordCount}字。

章节大纲：
{outline}{contextInfo}

创作要求：
1. 严格按照大纲进行创作
2. 内容丰富，情节生动
3. 人物形象鲜明，对话自然
4. 场景描写细致，氛围营造到位
5. 达到目标字数要求

请开始创作章节正文：";

        return await GenerateTextAsync(prompt, Math.Max(targetWordCount + 2000, 8000), 0.8f);
    }

    public async Task<ConsistencyCheckResult> CheckConsistencyAsync(string currentText, string previousContext)
    {
        var prompt = $@"请检查以下当前文本与之前上下文的一致性，重点关注：
1. 人物性格和行为是否一致
2. 情节发展是否合理
3. 时间线是否正确
4. 设定是否矛盾

请以JSON格式返回检查结果，格式如下：
{{
  ""isConsistent"": true/false,
  ""confidenceScore"": 0.0-1.0,
  ""issues"": [""问题描述1"", ""问题描述2""],
  ""suggestions"": [""建议1"", ""建议2""]
}}

之前的上下文：
{previousContext}

当前文本：
{currentText}";

        try
        {
            var response = await GenerateTextAsync(prompt, 2000, 0.3f);

            // 尝试解析JSON响应
            var jsonStart = response.IndexOf('{');
            var jsonEnd = response.LastIndexOf('}');

            if (jsonStart >= 0 && jsonEnd > jsonStart)
            {
                var jsonStr = response.Substring(jsonStart, jsonEnd - jsonStart + 1);
                var result = JsonSerializer.Deserialize<ConsistencyCheckResult>(jsonStr, new JsonSerializerOptions
                {
                    PropertyNameCaseInsensitive = true
                });

                if (result != null)
                {
                    return result;
                }
            }

            // 如果JSON解析失败，使用简单的文本解析
            var isConsistent = !response.ToLower().Contains("不一致") && !response.ToLower().Contains("矛盾");
            var confidenceScore = ExtractConfidenceScore(response);

            return new ConsistencyCheckResult
            {
                IsConsistent = isConsistent,
                ConfidenceScore = confidenceScore,
                Issues = ExtractIssues(response),
                Suggestions = ExtractSuggestions(response)
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "OpenAI一致性检查失败");
            return new ConsistencyCheckResult
            {
                IsConsistent = false,
                ConfidenceScore = 0.0f,
                Issues = new List<string> { $"检查过程出错: {ex.Message}" },
                Suggestions = new List<string> { "建议重新进行一致性检查" }
            };
        }
    }

    public async Task<string> GenerateOutlineAsync(string description, string outlineType)
    {
        var prompt = $"请根据以下描述生成{outlineType}大纲：\n{description}\n\n要求：\n1. 结构清晰，层次分明\n2. 内容丰富，具有可操作性\n3. 符合{outlineType}的特点和要求";
        return await GenerateTextAsync(prompt, 1500, 0.8f);
    }

    public async Task<List<CharacterInfo>> ExtractCharacterInfoAsync(string text)
    {
        var prompt = $"请从以下文本中提取角色信息，包括姓名、描述、关系等：\n{text}";
        var response = await GenerateTextAsync(prompt, 1000, 0.5f);
        
        // 简单解析响应，实际应用中可能需要更复杂的解析逻辑
        var characters = new List<CharacterInfo>();
        var lines = response.Split('\n', StringSplitOptions.RemoveEmptyEntries);
        
        foreach (var line in lines)
        {
            if (line.Contains("姓名") || line.Contains("角色"))
            {
                characters.Add(new CharacterInfo
                {
                    Name = line.Trim(),
                    Description = "从文本中提取的角色信息"
                });
            }
        }

        return characters;
    }

    private float ExtractConfidenceScore(string response)
    {
        try
        {
            // 尝试从响应中提取置信度分数
            var lines = response.Split('\n');
            foreach (var line in lines)
            {
                if (line.Contains("置信度") || line.Contains("confidence"))
                {
                    var numbers = System.Text.RegularExpressions.Regex.Matches(line, @"0\.\d+|\d+\.\d+");
                    if (numbers.Count > 0 && float.TryParse(numbers[0].Value, out var score))
                    {
                        return Math.Min(1.0f, Math.Max(0.0f, score));
                    }
                }
            }
            return 0.8f; // 默认置信度
        }
        catch
        {
            return 0.8f;
        }
    }

    private List<string> ExtractIssues(string response)
    {
        var issues = new List<string>();
        try
        {
            var lines = response.Split('\n');
            bool inIssuesSection = false;

            foreach (var line in lines)
            {
                if (line.Contains("问题") || line.Contains("issue"))
                {
                    inIssuesSection = true;
                    continue;
                }

                if (inIssuesSection && (line.Contains("建议") || line.Contains("suggestion")))
                {
                    break;
                }

                if (inIssuesSection && !string.IsNullOrWhiteSpace(line))
                {
                    var cleanLine = line.Trim().TrimStart('-', '*', '•', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '.', ' ');
                    if (!string.IsNullOrWhiteSpace(cleanLine))
                    {
                        issues.Add(cleanLine);
                    }
                }
            }
        }
        catch
        {
            // 忽略解析错误
        }

        return issues;
    }

    private List<string> ExtractSuggestions(string response)
    {
        var suggestions = new List<string>();
        try
        {
            var lines = response.Split('\n');
            bool inSuggestionsSection = false;

            foreach (var line in lines)
            {
                if (line.Contains("建议") || line.Contains("suggestion"))
                {
                    inSuggestionsSection = true;
                    continue;
                }

                if (inSuggestionsSection && !string.IsNullOrWhiteSpace(line))
                {
                    var cleanLine = line.Trim().TrimStart('-', '*', '•', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '.', ' ');
                    if (!string.IsNullOrWhiteSpace(cleanLine))
                    {
                        suggestions.Add(cleanLine);
                    }
                }
            }
        }
        catch
        {
            // 忽略解析错误
        }

        return suggestions;
    }
}
